var grids;
var context;

const THEME = {
    normal: {
        "0": "#CDC1B4",
        "2": "#EEE4DA",
        "4": "#EDE0C8",
        "8": "#F2B179",
        "16": "#F59563",
        "32": "#F67C5F",
        "64": "#F65E3B",
        "128": "#EDCF72",
        "256": "#EDCC61",
        "512": "#99CC00",
        "1024": "#83AF9B",
        "2048": "#0099CC",
        "2or4": "#645B52",
        "others": "#FFFFFF"
    },
    faded: {
        "0": "#D4C8BD",
        "2": "#EDE3DA",
        "4": "#EDE1D1",
        "8": "#F0CBAA",
        "16": "#F1BC9F",
        "32": "#F1AF9D",
        "64": "#F1A08B",
        "128": "#EDD9A6",
        "256": "#F6E5B0",
        "512": "#CDFF3F",
        "1024": "#CADCD4",
        "2048": "#75DBFF",
        "2or4": "#645B52",
        "others": "#FFFFFF"
    }
};
var colors = THEME.normal;

const SIDELEN = 70;
const MARGIN = 5;

export default {
    data: {
        bestScores: 9818,
        currentScores: 0,
        isShow: false
    },
    onInit() {
        this.initGrids();

        this.addTwoOrFourToGrids();
        this.addTwoOrFourToGrids();
    },
    initGrids() {
        grids = [[0, 0, 0, 0],
                 [0, 0, 0, 0],
                 [0, 0, 0, 0],
                 [0, 0, 0, 0]];
    },
    addTwoOrFourToGrids() {
        let array = [];
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                if (grids[row][column] == 0) {
                    array.push([row, column])
                }
            }
        }
        // array: [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1], [2, 2], [2, 3], [3, 0], [3, 1], [3, 2], [3, 3]]

        // Math.random(): [0, 1)之间的小数
        // Math.random() * 16: [0, 16)之间的小数
        // Math.floor(x): 小于等于x的最大整数
        // Math.floor(Math.random() * 16)：[0, 15]之间的整数
        // Math.floor(Math.random() * array.length)：[0, array.length-1]之间的整数
        let randomIndex = Math.floor(Math.random() * array.length);
        let row = array[randomIndex][0];           //array相当于2*array.length的二维数组
        let column = array[randomIndex][1];        //获得第randomIndex个空位的横纵坐标
        if (Math.random() < 0.8) {
            grids[row][column] = 2;
        } else {
            grids[row][column] = 4;
        }
    },
    onReady() {
        context = this.$refs.canvas.getContext('2d');//获得2d绘制引擎将其赋值给变量context
    },
    onShow() {
        this.drawGrids();
    },
    drawGrids() {
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                let gridStr = grids[row][column].toString();

                context.fillStyle = colors[gridStr]; //绘图填充颜色
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);

                context.font = "24px HYQiHei-65S";//设置字体
                if (gridStr != "0") {
                    if (gridStr == "2" || gridStr == "4") {
                        context.fillStyle = colors["2or4"];//字体颜色
                    } else {
                        context.fillStyle = colors["others"];
                    }

                    let offsetX = (4 - gridStr.length) * (SIDELEN / 8);
                    let offsetY = (SIDELEN - 24) / 2;
                    context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);//绘制字体
                }
            }
        }
    },
    swipeGrids(event) {
        let newGrids = this.changeGrids(event.direction);//根据方向移动场上格子，并将格子新的状态赋给一个新数组
        if (newGrids.toString() != grids.toString()) {//若两数组不同（格子发生了改变
            grids = newGrids;
            this.addTwoOrFourToGrids();//增添新的格子
            this.drawGrids();//绘制

            if (this.isGridsFull() == true && this.isGridsNotMergeable() == true) {//游戏结束
                this.gameover();
                //colors = THEME.faded;
                //this.drawGrids();
                //this.isShow = true;
            }
        }
    },
    gameover(){
        colors = THEME.faded;
        this.drawGrids();
        this.isShow = true;
    },
    isGridsFull() {
        if (grids.toString().split(",").indexOf("0") == -1) {//split() 方法用于把一个字符串分割成字符串数组。当找不到"0"时则说明全满
            return true;
        } else {
            return false;
        }
    },
    isGridsNotMergeable() {//用于判断结束条件
        for (let row = 0; row < 4; row++) {//遍历一遍判断每个格子在行方向与列方向是否有可合并的
            for (let column = 0; column < 4; column++) {
                if (column < 3) {//判断行方向上是否有可合并的格子只需前三列与它的下一列进行比较
                    if (grids[row][column] == grids[row][column + 1]) {//若当前格与行上下一格数字相同
                        return false;//一旦有可合并的函数就返回假，不用继续判断
                    }
                }
                if (row < 3) {//同理
                    if (grids[row][column] == grids[row + 1][column]) {
                        return false;
                    }
                }
            }
        }
        return true;//
    },
    changeGrids(direction) {
        let newGrids = [[0, 0, 0, 0],
                        [0, 0, 0, 0],
                        [0, 0, 0, 0],
                        [0, 0, 0, 0]];

        if (direction == 'left' || direction == 'right') {
            let step = 1;
            if (direction == 'right') {
                step = -1;//step作为循环时数组下标改变的方向
            }
            for (let row = 0; row < 4; row++) {//每一层
                let array = [];

                let column = 0;//如果为left则从0开始right从3开始，
                if (direction == 'right') {
                    column = 3;
                }
                for (let i = 0; i < 4; i++) {
                    if (grids[row][column] != 0) {//把所有非零元依次放入数组中
                        array.push(grids[row][column]);
                    }
                    column += step;//当direction为left时则从0向3递增，为right时则从3向0递减
                }
                for (let i = 0; i < array.length - 1; i++) {//访问当前元素及他的下一个元素，所有循环次数为length-1
                    if (array[i] == array[i + 1]) {//判断是否可合并，
                        array[i] += array[i + 1];//合并，
                        this.updateCurrentScores(array[i]);//更新分数
                        array[i + 1] = 0;//合并后参与合并的第二个元素消失
                        i++;
                    }
                }

                column = 0;
                if (direction == 'right') {
                    column = 3;
                }

                for (const elem of array) {
                    if (elem != 0) {//跳过array里的空元素
                        newGrids[row][column] = elem;//把合并后的状态赋给新数组grids，
                        column += step;
                    }
                }
            }
        } else if (direction == 'up' || direction == 'down') {
            let step = 1;
            if (direction == 'down') {
                step = -1;
            }

            for (let column = 0; column < 4; column++) {
                let array = [];

                let row = 0;
                if (direction == 'down') {
                    row = 3;
                }
                for (let i = 0; i < 4; i++) {
                    if (grids[row][column] != 0) {
                        array.push(grids[row][column]);
                    }
                    row += step;
                }
                for (let i = 0; i < array.length - 1; i++) {
                    if (array[i] == array[i + 1]) {
                        array[i] += array[i + 1];
                        this.updateCurrentScores(array[i]);
                        array[i + 1] = 0;
                        i++;
                    }
                }
                row = 0;
                if (direction == 'down') {
                    row = 3;
                }
                for (const elem of array) {
                    if (elem != 0) {
                        newGrids[row][column] = elem;
                        row += step;
                    }
                }
            }
        }
        return newGrids;
    },
    updateCurrentScores(gridNum) {
        this.currentScores += gridNum;
    },
    restartGame() {
        this.currentScores = 0;
        this.isShow = false;
        colors = THEME.normal;

        this.initGrids();

        this.addTwoOrFourToGrids();
        this.addTwoOrFourToGrids();

        this.drawGrids();
    }
}